package org.MySpringBoot;

import org.MySpringBoot.Annotations.Bean;
import org.MySpringBoot.Annotations.Component;
import org.MySpringBoot.Annotations.EnableConfigurationProperties;
import org.MySpringBoot.Utils.ClassScanner;

import java.lang.reflect.Method;
import java.util.Arrays;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
@Component
public class ApplicationContext
{
    public static void main(String[] args)
    {
        ApplicationContext.run(ApplicationContext.class);
    }
    public static final Map<String,Object> beanMap=new ConcurrentHashMap<>();//IoC容器
    public static void run(Class clz){//启动类的字节码
        init(clz.getPackage().getName());

    }
    private static void init(String basePackage) {
        List<Class<?>> classes = ClassScanner.scan(basePackage);

        // 第一轮：实例化 @Component 类
        for (Class<?> clazz : classes) {
            if (clazz.isAnnotationPresent(Component.class)) {
                try {
                    Object instance = clazz.getDeclaredConstructor().newInstance();
                    beanMap.put(String.valueOf(clazz), instance);
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        }

        // 第二轮：处理 @EnableConfigurationProperties
        for (Class<?> clazz : classes) {
            if (clazz.isAnnotationPresent(EnableConfigurationProperties.class)) {
                EnableConfigurationProperties anno = clazz.getAnnotation(EnableConfigurationProperties.class);
                Class<?> propClass = anno.value();
                try {
                    Object propInstance = propClass.getDeclaredConstructor().newInstance();
                    beanMap.put(String.valueOf(propClass), propInstance);
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        }

        // 第三轮：执行 @Bean 方法
        for (Class<?> clazz : classes) {
            if (clazz.isAnnotationPresent(Component.class)) {
                Object configInstance = beanMap.get(clazz);
                for (Method method : clazz.getDeclaredMethods()) {
                    if (method.isAnnotationPresent(Bean.class)) {
                        try {
                            // 检查方法参数：支持依赖注入
                            Object[] args = Arrays.stream(method.getParameterTypes())
                                    .map(beanMap::get)
                                    .toArray();
                            Object bean = method.invoke(configInstance, args);
                            beanMap.put(String.valueOf(method.getReturnType()), bean);
                        } catch (Exception e) {
                            e.printStackTrace();
                        }
                    }
                }
            }
        }
    }

    public <T> T getBean(Class<T> clazz) {
        return (T) beanMap.get(clazz);
    }
}
